package com.im;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.text.InputFilter;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

// 聊天活动
public class ChatActivity extends AppCompatActivity {
    // 聊天列表适配器
    static class ChatListAdapter extends BaseAdapter {
        // 聊天表项
        public static class ChatListItem {
            private final String mContent;  // 聊天内容
            private final int mIconIndex;   // 头像索引
            private final boolean mIsLeft;  // 左右标志，true 为左，false 为右
            private final String mTime;     // 发送时间

            /**
             * 构造方法。
             * @param content    聊天内容
             * @param iconIndex  头像索引
             * @param isLeft     左右标志，true 为左，false 为右
             * @param time       发送时间
             */
            public ChatListItem(String content, int iconIndex, boolean isLeft, String time) {
                mContent = content;
                mIconIndex = iconIndex;
                mIsLeft = isLeft;
                mTime = time;
            }

            /**
             * 获取聊天内容
             * @return 聊天内容
             */
            public String getContent() {
                return mContent;
            }

            /**
             * 获取头像索引
             * @return 头像索引
             */
            public int getIconIndex() {
                return mIconIndex;
            }

            /**
             * 获取发送时间
             * @return 发送时间
             */
            public String getTime() {
                return mTime;
            }

            /**
             * 判断在左边还是右边
             * @return 在左边则为 true，在右边则为 false
             */
            public boolean isLeft() {
                return mIsLeft;
            }
        }

        private final Map<String, List<ChatListItem>> mChatList;    // 与所有好友的全部聊天内容
        private LayoutInflater sInflater;                           // 布局填充者
        private List<ChatListItem> sItems;                          // 与当前好友的全部聊天内容

        /**
         * 构造方法。
         */
        public ChatListAdapter() {
            // 初始化成员
            mChatList = new HashMap<>();
        }

        /**
         * 添加一个表项。
         * @param friendName    好友名
         * @param chatInfo      聊天信息
         * @param isLeft        左右标志，true 为左，false 为右
         */
        public void addItem(String friendName, ChatInfo chatInfo, boolean isLeft) {
            // 获取好友名对应的所有聊天内容，如果好友名对应的所有聊天内容为空，则新建一个
            final List<ChatListItem> items = mChatList.computeIfAbsent(friendName, k -> new ArrayList<>());

            // 新建一个 ChatListItem 并加入到 items 中
            final ChatListItem item = new ChatListItem(chatInfo.mContent, chatInfo.mSrcIconIndex, isLeft, chatInfo.mTime);
            items.add(item);

            // 刷新列表控件
            if (friendName.equals(ChatActivity.getFriendName())) {
                sItems = items;
                super.notifyDataSetChanged();
            }
        }

        /**
         * 切换好友。
         * @param friendName 好友名
         */
        public void changeFriend(String friendName) {
            // 保存好友名
            sFriendName = friendName;

            // 获取好友名对应的聊天信息
            sItems = mChatList.get(friendName);

            // 更新聊天列表
            super.notifyDataSetChanged();
        }

        /**
         * 清除聊天记录。
         */
        public void clear() {
            mChatList.clear();
            super.notifyDataSetChanged();
        }

        /**
         * 获取表项的数量。
         * @return 表项的数量
         */
        @Override
        public int getCount() {
            if (sItems == null) {
                return 0;
            }
            return sItems.size();
        }

        /**
         * 获取表项。
         * @param item 表项的索引
         * @return 表项
         */
        @Override
        public Object getItem(int item) {
            if (sItems == null) {
                return null;
            }
            return sItems.get(item);
        }

        /**
         * 获取表项的 id。
         * @param item  表项的索引
         * @return 表项的 id
         */
        @Override
        public long getItemId(int item) {
            return item;
        }

        /**
         * 获取表项视图。
         * @param item          表项的索引
         * @param convertView   表项对应的视图
         * @param parent        父视图
         * @return 表项视图
         */
        @SuppressLint("InflateParams")
        @Override
        public View getView(int item, View convertView, ViewGroup parent) {
            if (sItems == null) {
                return convertView;
            }

            // 获取表项
            final ChatListItem chatListItem = sItems.get(item);
            final boolean isLeft = chatListItem.isLeft();

            // 获取表项对应的视图
            if (isLeft) {
                convertView = sInflater.inflate(R.layout.item_chat_left, null);
            } else {
                convertView = sInflater.inflate(R.layout.item_chat_right, null);
            }

            // 获取"发送时间"标签
            final TextView tvTime = convertView.findViewById(R.id.IDC_TEXT_TIME);

            // 获取用户头像控件
            final ImageView ivUserIcon = convertView.findViewById(R.id.IDC_IMAGE_USER_ICON);

            // 获取"聊天内容"标签
            final TextView tvContent = convertView.findViewById(R.id.IDC_TEXT_CONTENT);

            // 设置发送时间
            tvTime.setText(chatListItem.getTime());

            // 设置用户头像
            ivUserIcon.setImageResource(chatListItem.getIconIndex() + R.mipmap.normal00);

            // 设置聊天内容
            tvContent.setText(chatListItem.getContent());

            return convertView;
        }

        /**
         * 设置布局填充者。
         * @param inflater  布局填充者
         */
        public void setInflater(LayoutInflater inflater) {
            sInflater = inflater;
        }
    }

    private EditText mEditInput;                    // 编辑框
    private ListView mListviewChat;                 // 聊天历史控件
    private static final ChatListAdapter sAdapter;  // 内容提供者
    private static String sFriendName;              // 好友名

    static {
        sAdapter = new ChatListAdapter();
        sFriendName = "";
    }

    /**
     * 添加一个表项。
     * @param friendName    好友名
     * @param chatInfo      聊天信息
     */
    public void addItem(String friendName, ChatInfo chatInfo) {
        // 显示聊天内容
        final boolean isLeft = !Client.getUsername().equals(chatInfo.mSrcUsername);
        sAdapter.addItem(friendName, chatInfo, isLeft);

        // 滚动到底部
        mListviewChat.setSelection(mListviewChat.getCount() - 1);
    }

    /**
     * 切换好友。
     * @param friendName    好友名
     */
    private void changeFriend(String friendName) {
        // 如果是当前好友，则直接返回
        if (friendName.equals(sFriendName)) {
            return;
        }

        // 切换好友
        sAdapter.changeFriend(friendName);

        // 设置标题
        super.setTitle(friendName);
    }

    /**
     * 清除聊天内容。
     */
    public static void clear() {
        if (sAdapter != null) {
            sAdapter.clear();
        }
    }

    /**
     * 获取好友名。
     * @return 好友名
     */
    public static String getFriendName() {
        return sFriendName;
    }

    /**
     * "发送"按钮的单击响应方法。
     * @param view  按钮
     */
    public void onButtonSendClicked(View view) {
        // 获取用户输入的聊天内容
        final String content = mEditInput.getText().toString();
        if (TextUtils.isEmpty(content.trim())) {
            return;
        }

        // 获取当前时间
        final String time = new SimpleDateFormat(Const.DATE_TIME_FORMAT, Locale.getDefault()).format(new Date());

        // 显示聊天内容
        final ChatInfo chatInfo = new ChatInfo(content, sFriendName, Client.getIconIndex(), Client.getUsername(), time);
        this.addItem(sFriendName, chatInfo);

        // 清空聊天内容编辑框
        mEditInput.setText("");

        // 发送聊天内容
        final Intent intent = new Intent(Const.INTENT_CHAT_C2S);
        intent.putExtra(ChatInfo.class.getName(), chatInfo);
        super.sendBroadcast(intent);
    }

    /**
     * 创建事件的响应方法。
     * @param savedInstanceState    保存的实例状态
     */
    @SuppressLint("MissingSuperCall")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.setContentView(R.layout.activity_chat);

        // 初始化成员
        mListviewChat = super.findViewById(R.id.IDC_LIST_CHAT);
        mEditInput = super.findViewById(R.id.IDC_EDIT_INPUT);
        mEditInput.setFilters(new InputFilter[]{new InputFilter.LengthFilter(Const.MAX_CONTENT_LEN)});
        mEditInput.requestFocus();
        sAdapter.setInflater(super.getLayoutInflater());
        mListviewChat.setAdapter(sAdapter);

        // 处理意图
        this.onGetIntent(super.getIntent());
    }

    /**
     * 处理接收到的意图。
     * @param intent    意图
     */
    private void onGetIntent(Intent intent) {
        // 获取好友名
        String friendName = intent.getStringExtra(Const.KEY_FRIEND_NAME);

        // 切换好友
        if (TextUtils.isEmpty(friendName)) {
            final ChatInfo chatInfo = (ChatInfo)intent.getSerializableExtra(Const.KEY_CHAT_INFO);
            if (chatInfo != null) {
                final boolean isMultiChat = chatInfo.mDstUsername.equals(ImProtocol.MULTI_CHAT);
                friendName = isMultiChat ? chatInfo.mDstUsername: chatInfo.mSrcUsername;
                this.addItem(friendName, chatInfo);
                this.changeFriend(friendName);
            }
        } else {
            this.changeFriend(friendName);
        }
    }

    /**
     * 接收到新的意图的响应方法。
     * @param intent    意图
     */
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        this.onGetIntent(intent);
    }

    /**
     * 恢复事件的响应方法。
     */
    @Override
    public void onResume() {
        super.onResume();
        
        // 滚动到最下面一行
        mListviewChat.setSelection(mListviewChat.getCount() - 1);
    }
}
